package cn.ht.jywrwater.module.ht.service.regionwateranalysis;

import cn.ht.jywrwater.module.ht.controller.admin.waterleakageanalysis.vo.WaterLeakageAnalysisVO;
import cn.ht.jywrwater.module.ht.controller.admin.waterleakageanalysis.vo.WaterLeakageData;
import cn.ht.jywrwater.module.ht.dal.dataobject.waterleakageanalysis.WaterLeakageAnalysisDO;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import cn.ht.jywrwater.module.ht.controller.admin.regionwateranalysis.vo.*;
import cn.ht.jywrwater.module.ht.dal.dataobject.regionwateranalysis.RegionWaterAnalysisDO;
import cn.ht.jywrwater.framework.common.pojo.PageResult;

import cn.ht.jywrwater.module.ht.convert.regionwateranalysis.RegionWaterAnalysisConvert;
import cn.ht.jywrwater.module.ht.dal.mysql.regionwateranalysis.RegionWaterAnalysisMapper;

import static cn.ht.jywrwater.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.ht.jywrwater.module.ht.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 区域用水分析统计 Service 实现类
 *
 * @author hzx
 */
@Service
@Validated
public class RegionWaterAnalysisServiceImpl implements RegionWaterAnalysisService {

    @Resource
    private RegionWaterAnalysisMapper regionWaterAnalysisMapper;

    @Override
    public Long createRegionWaterAnalysis(RegionWaterAnalysisCreateReqVO createReqVO) {
        // 插入
        RegionWaterAnalysisDO regionWaterAnalysis = RegionWaterAnalysisConvert.INSTANCE.convert(createReqVO);
        regionWaterAnalysisMapper.insert(regionWaterAnalysis);
        // 返回
        return regionWaterAnalysis.getId();
    }

    @Override
    public void updateRegionWaterAnalysis(RegionWaterAnalysisUpdateReqVO updateReqVO) {
        // 校验存在
        validateRegionWaterAnalysisExists(updateReqVO.getId());
        // 更新
        RegionWaterAnalysisDO updateObj = RegionWaterAnalysisConvert.INSTANCE.convert(updateReqVO);
        regionWaterAnalysisMapper.updateById(updateObj);
    }

    @Override
    public void deleteRegionWaterAnalysis(Long id) {
        // 校验存在
        validateRegionWaterAnalysisExists(id);
        // 删除
        regionWaterAnalysisMapper.deleteById(id);
    }

    private void validateRegionWaterAnalysisExists(Long id) {
        if (regionWaterAnalysisMapper.selectById(id) == null) {
            throw exception(REGION_WATER_ANALYSIS_NOT_EXISTS);
        }
    }

    @Override
    public RegionWaterAnalysisDO getRegionWaterAnalysis(Long id) {
        return regionWaterAnalysisMapper.selectById(id);
    }

    @Override
    public List<RegionWaterAnalysisDO> getRegionWaterAnalysisList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return regionWaterAnalysisMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<RegionWaterAnalysisDO> getRegionWaterAnalysisPage(RegionWaterAnalysisPageReqVO pageReqVO) {
        return regionWaterAnalysisMapper.selectPage(pageReqVO);
    }

    @Override
    public List<RegionWaterAnalysisDO> getRegionWaterAnalysisList(RegionWaterAnalysisExportReqVO exportReqVO) {
        return regionWaterAnalysisMapper.selectList(exportReqVO);
    }

    @Override
    public RegionWaterAnalysisVO regionWaterAnalysis(String region, LocalDate beginDate, LocalDate endDate) {

        RegionWaterAnalysisVO regionWaterAnalysisVO = new RegionWaterAnalysisVO();
        regionWaterAnalysisVO.setRegion(region);
        QueryWrapper<RegionWaterAnalysisDO> queryWrapper = new QueryWrapper<>();
        if (region!=null && !region.equals("")){
            queryWrapper.eq("region", region);
        }
        if (beginDate!=null){
            queryWrapper.ge("data_date", beginDate);
        }
        if (endDate!=null){
            queryWrapper.le("data_date", endDate);
        }

        List<RegionWaterAnalysisDO> regionWaterAnalysisList = regionWaterAnalysisMapper.selectList(queryWrapper);


        if (regionWaterAnalysisList.size()>0){
            // 用户总量
            Integer userCount = regionWaterAnalysisList.stream()
                    .map(RegionWaterAnalysisDO::getUserCount).reduce(Integer::sum).get();

            // 总供水量
            Integer waterCount = regionWaterAnalysisList.stream()
                    .map(RegionWaterAnalysisDO::getWaterCount).reduce(Integer::sum).orElse(0);

            // 抄表总量
            Integer readMeterCount = regionWaterAnalysisList.stream()
                    .map(RegionWaterAnalysisDO::getReadMeterCount).reduce(Integer::sum).orElse(0);

            // 损耗量
            Integer attritionCount = regionWaterAnalysisList.stream()
                    .map(RegionWaterAnalysisDO::getAttritionCount).reduce(Integer::sum).orElse(0);

            // 损耗率
            Double attritionRate = regionWaterAnalysisList.stream()
                    .mapToDouble(RegionWaterAnalysisDO::getWaterCount).sum( );


            regionWaterAnalysisVO.setUserCount(userCount);
            regionWaterAnalysisVO.setWaterCount(waterCount);
            regionWaterAnalysisVO.setReadMeterCount(readMeterCount);
            regionWaterAnalysisVO.setAttritionCount(attritionCount);
            regionWaterAnalysisVO.setAttritionRate(attritionRate);

            // 日期的漏算分析

            Map<LocalDate, RegionWaterDate> dateData = MapUtil.newHashMap();
            List<LocalDate> difDateList = regionWaterAnalysisList.stream().map(RegionWaterAnalysisDO::getDataDate).distinct().collect(Collectors.toList());
//            // 所有供水list
//            List<RegionWaterAnalysisDO> waterLeakageAnalysisDateProvideList = regionWaterAnalysisList.stream()
//                    .filter(waterLeakageAnalysis -> waterLeakageAnalysis.getType() == 0).collect(Collectors.toList());
//            // 有效供水list
//            List<RegionWaterAnalysisDO> waterLeakageAnalysisDateEffectiveList = regionWaterAnalysisList.stream()
//                    .filter(waterLeakageAnalysis -> waterLeakageAnalysis.getType() == 1).collect(Collectors.toList());
            for (LocalDate difDate:difDateList){
                Integer userCountDate = regionWaterAnalysisList.stream()
                        .filter(waterLeakageAnalysis -> waterLeakageAnalysis.getDataDate().equals(difDate)).map(RegionWaterAnalysisDO::getUserCount).reduce(Integer::sum).orElse(0);
                Integer waterCountDate = regionWaterAnalysisList.stream()
                        .filter(regionWaterAnalysis -> regionWaterAnalysis.getDataDate().equals(difDate)).map(RegionWaterAnalysisDO::getWaterCount).reduce(Integer::sum).orElse(0);
                Integer readMeterCountDate = regionWaterAnalysisList.stream()
                        .filter(waterLeakageAnalysis -> waterLeakageAnalysis.getDataDate().equals(difDate)).map(RegionWaterAnalysisDO::getReadMeterCount).reduce(Integer::sum).orElse(0);
                Integer attritionCountDate = regionWaterAnalysisList.stream()
                        .filter(regionWaterAnalysis -> regionWaterAnalysis.getDataDate().equals(difDate)).map(RegionWaterAnalysisDO::getAttritionCount).reduce(Integer::sum).orElse(0);
                Double attritionRateDate = regionWaterAnalysisList.stream()
                        .filter(regionWaterAnalysis -> regionWaterAnalysis.getDataDate().equals(difDate)).map(RegionWaterAnalysisDO::getAttritionRate).reduce(Double::sum).get();

                RegionWaterDate regionWaterDate = new RegionWaterDate();
                regionWaterDate.setUserCount(userCountDate);
                regionWaterDate.setWaterCount(waterCountDate);
                regionWaterDate.setReadMeterCount(readMeterCountDate);
                regionWaterDate.setAttritionCount(attritionCountDate);
                regionWaterDate.setAttritionRate(attritionRateDate);
                dateData.put(difDate,regionWaterDate);
            }
            regionWaterAnalysisVO.setDateData(dateData);
        }


        return regionWaterAnalysisVO;


    }

}
